/*Name: cesar.cpp
  Last Modification: 31/05/10 16:42
  Description: fichier regroupant toutes les fonctions necessaires au fonctionnement de cesar et à son exportation
  License: GNU GPL v3
    Copyright (C) 2012 G. Bonnoron, P.Brunet, C. Duchene et F. Cornevaux-Juignet

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.*/

//inclusion du header
#include "cesar.h"

//Constructeur de Cesar en faisant appel au constructeur de sa classe mère Algorithme
Cesar::Cesar() : Algorithme()
{
    clef=3; //Historiquement cette valeur était la clef utilisée par César lui-même
    cle = new QLineEdit(QString::fromUtf8("Entrez votre clé ici"));
    crypter = new QTextEdit(QString::fromUtf8("Vos données (dé)chiffrées apparaîtront ici"));
}

//fonction permettant d'effectuer un décalage de "decale" sur un QChar "lettre" pour un alphabet ascii entre
// 32 et 127 qui sont des caractères affichables de la table ascii. On traite le cas particulier du saut de ligne.
QChar Cesar::changeLettre(QChar lettre,int decale)
{
    if(lettre == '\n'){
        return '\n';
    }
    else{
        int sortie = (lettre.toAscii()-32+decale);
        while(sortie < 0)
            sortie += (127-32);
        return  QChar((unsigned char)((sortie)%(127-32)+32));
    }
}

//fonction permettant de chiffrer les donées entrées par l'utilisateur
void Cesar::chiffre(bool fich)
{
    QTime mesure;  //Pour calculer le temps d'exécution du chiffrement
    clef=(cle->text()).toInt();         //Pour prendre en compte la nouvelle clef entrée par l'utilisateur
    mesure.start();
    if(fich){           //On traite le cas d'un chiffrement de fichier
        lineOut.clear();        //on vide la chaine de sortie qui est un QByteArray
        for (int i = 0; i<line.length();i++){
        //Dans le cas d'un chiffrement de fichier, on chiffre octet par octet. C'est pourquoi la clef doit être entre 0 et 256
        //On effectue donc un décalage de clef modulo 256 pour le chiffrement puis on inscrit le résultat à la suite dans le fichier
            lineOut.append(line[i]+clef%256);
        }
    }
    else{   //Dans le cas d'un chiffrement de texte entré manuellement
        messageOut = "";    //On vide la chaine de caractères sortante
        for (int i = 0; i<messageIn.length();i++){
            //Dans ce cas, on chiffre caractère par caractère donc on effectue un modulo sur la taille de l'alphabet
            //puis on modifie les lettres
            messageOut+=changeLettre(messageIn[i],clef%(127-32));
        }
    }
    //On envoie les données en sortie
    this->outCesar(fich);
    temps = mesure.elapsed();
}

//fonction permettant le déchiffrement des donées entrées par l'utilisateur. Le fonctionnement est le même que
// pour la fonction chiffre mais le décalage est de -clef et non clef
void Cesar::dechiffre(bool fich)
{
    QTime mesure;
    clef=(cle->text()).toInt();
    mesure.start();
    if(fich){
        lineOut.clear();
        for (int i = 0; i<line.length();i++){
            lineOut.append(line[i]-(clef%256));
        }
    }
    else{
        messageOut = "";
        for (int i = 0; i<messageIn.length();i++){
            messageOut+=changeLettre(messageIn[i],-(clef%(127-32)));
        }
    }
    this->outCesar(fich);
    temps = mesure.elapsed();
}

//fonction permettant de donner le texte chiffré ou déchiffré à l'utilisateur
void Cesar::outCesar(bool fichier)
{
    if(fichier){ //Si le texte en entrée est un fichier, le texte en sortie l'est également
        if(fileOut.isEmpty())   //On écrit dans le fichier choisi par l'utilisateur si celui a entré un nom de fichier
            fileOut = "out_Cesar.txt";
        QFile file(fileOut);
        if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate))
            crypter->setText(QString("Erreur lors du l'écriture fichier"));
        else{
            file.write(lineOut);
            //On avertit l'utilisateur que tout s'est bien passé et du lieu d'écriture
            crypter->setText(QString("sortie dans " + fileOut));
        }
    }
    else{   //Si le texte est entré dans la plate-forme, il ressort de la même façon
        crypter->setText(messageOut);
    }
}

//On définit l'affichage de cet algorithme comme une liste de widget
QList<QWidget *> Cesar::affiche()
{
    QList<QWidget* > liste = QList<QWidget *>();
    QLabel* texte = new QLabel(QString::fromUtf8("<h1> Code César :</h1>"));
    liste.append(texte);
    liste.append(cle);
    liste.append(crypter);
    return liste;
}

//On définit l'aide comme pour chaque algorithme pour expliquer son fonctionnement
QString Cesar::aide()
{
    QString sortie;
    sortie.append(QString::fromUtf8("<h1>Code César</h1>"));
    sortie.append(QString::fromUtf8("<h2>Le principe</h2><div align = 'justify'> Cet algorithme a été mis en place par le consul romain Jules César lors de la Guerre des Gaules pour éviter que les messages envoyés à ses généraux ne puissent être compris en cas d'interception. "));
    sortie.append(QString::fromUtf8("C'est un algorithme de substitution à clé symétrique. Le principe est de décaler les lettres d'un texte d'un nombre fixe de lettres. Cependant, cette méthode est peu fiable, puisque, chaque lettre étant toujours chiffrée de la même façon, une analyse de fréquences permet de casser le code. "));
    sortie.append(QString::fromUtf8("Nous avons alors généralisé son utilisation grâce à l'utilisation de l'ASCII pour les textes et grâce à l'utilisation du codage bits à bits dans le cadre des fichiers. </div>"));
    sortie.append(QString::fromUtf8("<h2>L'utiliser dans le cadre de la plate-forme</h2>Vous pouvez entrer une clé dans le champ prévu. Cette clé doit être un entier et détermine le décalage que vous souhaitez avoir."));
    return sortie;
}

//fonction permettant de retrouver le nom de l'algorithme
QString Cesar::nom()
{
    return QString::fromUtf8("César");
}

//Destructeur de l'algorithme
Cesar::~Cesar()
{
}

//Pour l'export de la bibliothèque
extern "C" MY_EXPORT Algorithme* maker()
{
    return new Cesar();
}
